package com.nuonuo.nuo_xp;

/**
 * @author glsite.com
 * @version $Rev$
 * @des ${TODO}
 * @updateAuthor $Author$
 * @updateDes ${TODO}
 */

import android.util.Base64;
import android.util.Log;
import javax.crypto.Cipher;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

/**
 * Hook通杀DES_DESede_AES
 *
 *javax.crypto.spec.SecretKeySpec
 * javax.crypto.spec.IvParameterSpec
 * javax.crypto.Cipher
 */

public class HOOK_AES_DES implements IXposedHookLoadPackage {
    private String log_d_tag="XP";
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        Log.d(log_d_tag,"注入成功...");
        Log.d(log_d_tag,"***对称加密算法***");
        Log.d(log_d_tag,"javax.crypto.spec.SecretKeySpec");
        Log.d(log_d_tag,"javax.crypto.spec.IvParameterSpec");
        Log.d(log_d_tag,"javax.crypto.Cipher");
        Log.d(log_d_tag,"活动APP包名:"+loadPackageParam.packageName);
        //Hook 密钥 （DES MAC AES 3DES）
        XposedBridge.hookAllConstructors(XposedHelpers.findClass("javax.crypto.spec.SecretKeySpec",
                loadPackageParam.classLoader),  new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                byte[] screKey = (byte[]) param.args[0];//第一个必为密钥
                Integer offset = 0;
                Integer size = 0;
                String algorithm = "";
                if (param.args.length!=2){
                    offset = (Integer) param.args[1];
                    size = (Integer) param.args[2];
                    algorithm = (String) param.args[3];
                }else {
                    size = screKey.length;
                    algorithm = (String) param.args[1];
                }
                byte[] keyByte = new byte[size];
                System.arraycopy(screKey,offset,keyByte,0,size);
                String data = new String(keyByte);
                String dataHex = Utils.byteToHexString(keyByte);
                String dataBase64 = Base64.encodeToString(keyByte,0);
                Log.d(log_d_tag,"-");
                Log.d(log_d_tag,"-");
                Log.d(log_d_tag,"==========================================HOOK开始=======================================");
                Log.d(log_d_tag,"====================================Class_AES_DES(HMAC)==================================");
                Log.d(log_d_tag,algorithm+"_screKey_Data:"+data);
                Log.d(log_d_tag,algorithm+"_screKey_Data_Hex:"+dataHex);
                Log.d(log_d_tag,algorithm+"_screKey_Data_Base64:"+dataBase64);
                Log.d(log_d_tag,"===================================密钥=================================================");
                Log.d(log_d_tag,"==================================算法:"+algorithm+"====================================");
                Log.d(log_d_tag,"=====================================HOOK结束===========================================");
                Log.d(log_d_tag,"=====================================调用堆栈~开始==============================================");
                Log.d(log_d_tag,Log.getStackTraceString(new Throwable()));
                Log.d(log_d_tag,"=====================================调用堆栈~结束==============================================");
            }
        });
        //hook DES_DESede_AES 的iv值
        XposedBridge.hookAllConstructors(XposedHelpers.findClass("javax.crypto.spec.IvParameterSpec",
                loadPackageParam.classLoader), new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                byte[] ivr = (byte[]) param.args[0];//第一个必定iv
                String algorithm = "Ivr_";
                int offset = 0;
                int len = 0;
                if (param.args.length != 1){//IvParameterSpec(byte[] iv, int offset, int len)
                    offset = (int) param.args[1];
                    len = (int) param.args[2];
                }else {//IvParameterSpec(byte[] iv)
                    len = ivr.length;
                }
                byte[] taget = new byte[len];
                System.arraycopy(ivr,offset,taget,0,len);
                String data = new String(taget);
                String dataHex = Utils.byteToHexString(taget);
                String dataBase64 = Base64.encodeToString(taget,0);
                Log.d(log_d_tag,"-");
                Log.d(log_d_tag,"-");
                Log.d(log_d_tag,"=====================================HOOK开始==========================================");
                Log.d(log_d_tag,"====================================Class_AES_DES==================================");
                Log.d(log_d_tag,algorithm+"_update_Data:"+data);
                Log.d(log_d_tag,algorithm+"_update_Data_Hex:"+dataHex);
                Log.d(log_d_tag,algorithm+"_update_Data_Base64:"+dataBase64);
                Log.d(log_d_tag,"====================================加密IV=============================================");
                Log.d(log_d_tag,"==================================算法:"+algorithm+"====================================");
                Log.d(log_d_tag,"=====================================HOOK结束===========================================");
                Log.d(log_d_tag,"=====================================调用堆栈~开始==============================================");
                Log.d(log_d_tag,Log.getStackTraceString(new Throwable()));
                Log.d(log_d_tag,"=====================================调用堆栈~结束==============================================");
            }
        });
        //hook DES_DESede_AES
        XposedBridge.hookAllMethods(XposedHelpers.findClass("javax.crypto.Cipher", loadPackageParam.classLoader),
                "update", new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Cipher cipher = (Cipher)param.thisObject;
                        String algorithm = cipher.getAlgorithm();//Cipher.getInstance(String transformation)  transformation就是Algorithm
                        byte[] bytes = (byte[]) param.args[0];
                        String data = new String(bytes);
                        String dataHex = Utils.byteToHexString(bytes);
                        String dataBase64 = Base64.encodeToString(bytes,0);
                        Log.d(log_d_tag,"-");
                        Log.d(log_d_tag,"-");
                        Log.d(log_d_tag,"================================HOOK开始==================================================");
                        Log.d(log_d_tag,"================================Class_AES_DES=============================================");
                        Log.d(log_d_tag,algorithm+"_update_Data:"+data);
                        Log.d(log_d_tag,algorithm+"_update_Data_Hex:"+dataHex);
                        Log.d(log_d_tag,algorithm+"_update_Data_Base64:"+dataBase64);
                        Log.d(log_d_tag,"============================算法:"+algorithm+"方法:update==================================");
                        Log.d(log_d_tag,"=====================================HOOK结束==============================================");
                        Log.d(log_d_tag,"=====================================调用堆栈~开始==============================================");
                        Log.d(log_d_tag,Log.getStackTraceString(new Throwable()));
                        Log.d(log_d_tag,"=====================================调用堆栈~结束==============================================");
                    }
                });

        //加密值
        XposedBridge.hookAllMethods(XposedHelpers.findClass("javax.crypto.Cipher", loadPackageParam.classLoader),
                "doFinal", new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        //if(param.args==null){return;}
                        //if(!(param.args.length == 0 || param.args.length == 1 || param.args.length == 3))return;
                        //Log.e("Stack","Stack",new Throwable("stack dump"));
                        /*if (param.args==null){
                            Log.d(log_d_tag,"============param为null=========================");
                        }*/
                        Cipher cipher = (Cipher)param.thisObject;
                        String algorithm = cipher.getAlgorithm();
                        if (param.args!=null && param.args.length ==1){
                            byte[] bytes = (byte[]) param.args[0];
                            String data = new String(bytes);
                            String dataHex = Utils.byteToHexString(bytes);
                            String dataBase64 = Base64.encodeToString(bytes,0);
                            Log.d(log_d_tag,"-");
                            Log.d(log_d_tag,"-");
                            Log.d(log_d_tag,"===================================HOOK开始================================================");
                            Log.d(log_d_tag,"===================================Class_AES_DES===========================================");
                            Log.d(log_d_tag, "-dofinal方法参数个数为 1");
                            String parameter_length = param.args.length+"";
                            Log.d(log_d_tag,"parameter_length:"+parameter_length);
                            Log.d(log_d_tag,algorithm+"_doFinal_Data:"+data);
                            Log.d(log_d_tag,algorithm+"_doFinal_Data_Hex:"+dataHex);
                            Log.d(log_d_tag,algorithm+"_doFinal_Data_Base64:"+dataBase64);
                            Log.d(log_d_tag,"============================算法:"+algorithm+"方法:doFinal==================================");
                            Log.d(log_d_tag,"=====================================HOOK结束==============================================");
                        }else if (param.args!=null && param.args.length == 3){//	doFinal(byte[] input, int inputOffset, int inputLen)
                            byte[] bytes = (byte[]) param.args[0];
                            int inputOffset = (int) param.args[1];
                            int inputLen = (int) param.args[2];
                            byte[] taget = new byte[inputLen];
                            System.arraycopy(bytes,inputOffset,taget,0,inputLen);
                            String data = new String(taget);
                            String dataHex = Utils.byteToHexString(taget);
                            String dataBase64 = Base64.encodeToString(taget,0);
                            Log.d(log_d_tag,"-");
                            Log.d(log_d_tag,"-");
                            Log.d(log_d_tag,"=====================================HOOK开始==============================================");
                            Log.d(log_d_tag,"===================================Class_AES_DES===========================================");
                            Log.d(log_d_tag, "-dofinal方法参数个数为 3");
                            Log.d(log_d_tag, "-这个部分主要是对明文进行截取操作");
                            String parameter_length = param.args.length+"";
                            Log.d(log_d_tag,"parameter_length:"+parameter_length);
                            Log.d(log_d_tag,algorithm+"_doFinal_Data:"+data);
                            Log.d(log_d_tag,algorithm+"_doFinal_Data_Hex:"+dataHex);
                            Log.d(log_d_tag,algorithm+"_doFinal_Data_Base64:"+dataBase64);
                            Log.d(log_d_tag,"============================算法:"+algorithm+"方法:doFinal==================================");
                            Log.d(log_d_tag,"=====================================HOOK结束==============================================");
                        }
                        byte[] bytes = (byte[]) param.getResult();
                        String dataHex = Utils.byteToHexString(bytes);
                        String dataBase64 = Base64.encodeToString(bytes,0);
                        Log.d(log_d_tag,"-");
                        Log.d(log_d_tag,"-");
                        Log.d(log_d_tag,"==================================HOOK开始=================================================");
                        Log.d(log_d_tag,"===================================Class_AES_DES===========================================");
                        Log.d(log_d_tag, "--dofinal方法没有参数");
                        Log.d(log_d_tag,algorithm+"_doFina_lData_Hex_Result:"+dataHex);
                        Log.d(log_d_tag,algorithm+"_doFina_lData_Base64_Result:"+dataBase64);
                        Log.d(log_d_tag,"============================算法:"+algorithm+"方法:doFinal==================================");
                        Log.d(log_d_tag,"=====================================HOOK结束==============================================");
                        Log.d(log_d_tag,"=====================================调用堆栈~开始==============================================");
                        Log.d(log_d_tag,Log.getStackTraceString(new Throwable()));
                        Log.d(log_d_tag,"=====================================调用堆栈~结束==============================================");
                    }
                });

    }
}
